/*
 * Copyright (C) 2011 ArkCORE <http://www.arkania.net/>

 * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

/* ScriptData
 SDName: Borean_Tundra
 SD%Complete: 100
 SDComment: Quest support: 11708. Taxi vendors.
 SDCategory: Borean Tundra
 EndScriptData */

/* ContentData
 npc_iruk
 npc_corastrasza
 npc_jenny
 npc_sinkhole_kill_credit
 npc_khunok_the_behemoth
 npc_scourge_prisoner
 mob_nerubar_victim
 npc_keristrasza
 npc_nesingwary_trapper
 npc_lurgglbr
 npc_nexus_drake_hatchling
 EndContentData */

#include "ScriptPCH.h"
#include "ScriptedEscortAI.h"
#include "ScriptedFollowerAI.h"

/*######
 ## npc_sinkhole_kill_credit
 ######*/

enum eSinkhole {
	SPELL_SET_CART = 46797,
	SPELL_EXPLODE_CART = 46799,
	SPELL_SUMMON_CART = 46798,
	SPELL_SUMMON_WORM = 46800,
};

class npc_sinkhole_kill_credit: public CreatureScript {
public:
	npc_sinkhole_kill_credit() :
			CreatureScript("npc_sinkhole_kill_credit") {
	}

	struct npc_sinkhole_kill_creditAI: public ScriptedAI {
		npc_sinkhole_kill_creditAI(Creature* c) :
				ScriptedAI(c) {
		}

		uint32 uiPhaseTimer;
		uint8 Phase;
		uint64 casterGuid;

		void Reset() {
			uiPhaseTimer = 500;
			Phase = 0;
			casterGuid = 0;
		}

		void SpellHit(Unit* caster, const SpellEntry* spell) {
			if (Phase)
				return;

			if (spell->Id == SPELL_SET_CART
					&& caster->GetTypeId() == TYPEID_PLAYER
					&& CAST_PLR(caster)->GetQuestStatus(11897)
							== QUEST_STATUS_INCOMPLETE) {
				Phase = 1;
				casterGuid = caster->GetGUID();
			}
		}

		void EnterCombat(Unit* /*who*/) {
		}

		void UpdateAI(const uint32 diff) {
			if (!Phase)
				return;

			if (uiPhaseTimer <= diff) {
				switch (Phase) {
				case 1:
					DoCast(me, SPELL_EXPLODE_CART, true);
					DoCast(me, SPELL_SUMMON_CART, true);
					if (GameObject* cart = me->FindNearestGameObject(188160, 3))
						cart->SetUInt32Value(GAMEOBJECT_FACTION, 14);
					uiPhaseTimer = 3000;
					Phase = 2;
					break;
				case 2:
					if (GameObject* cart = me->FindNearestGameObject(188160, 3))
						cart->UseDoorOrButton();
					DoCast(me, SPELL_EXPLODE_CART, true);
					uiPhaseTimer = 3000;
					Phase = 3;
					break;
				case 3:
					DoCast(me, SPELL_EXPLODE_CART, true);
					uiPhaseTimer = 2000;
					Phase = 4;
				case 5:
					DoCast(me, SPELL_SUMMON_WORM, true);
					if (Unit* worm = me->FindNearestCreature(26250, 3)) {
						worm->SetFlag(UNIT_FIELD_FLAGS,
								UNIT_FLAG_NOT_SELECTABLE);
						worm->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE);
					}
					uiPhaseTimer = 1000;
					Phase = 6;
					break;
				case 6:
					DoCast(me, SPELL_EXPLODE_CART, true);
					if (Unit* worm = me->FindNearestCreature(26250, 3)) {
						me->Kill(worm);
						worm->RemoveFlag(UNIT_DYNAMIC_FLAGS,
								UNIT_DYNFLAG_LOOTABLE);
					}
					uiPhaseTimer = 2000;
					Phase = 7;
					break;
				case 7:
					DoCast(me, SPELL_EXPLODE_CART, true);
					if (Player* caster = Unit::GetPlayer(*me, casterGuid))
						caster->KilledMonster(me->GetCreatureInfo(),
								me->GetGUID());
					uiPhaseTimer = 5000;
					Phase = 8;
					break;
				case 8:
					EnterEvadeMode();
					break;
				}
			} else
				uiPhaseTimer -= diff;
		}
	};

	CreatureAI* GetAI(Creature* creature) const {
		return new npc_sinkhole_kill_creditAI(creature);
	}
};

/*######
 ## npc_khunok_the_behemoth
 ######*/

class npc_khunok_the_behemoth: public CreatureScript {
public:
	npc_khunok_the_behemoth() :
			CreatureScript("npc_khunok_the_behemoth") {
	}

	struct npc_khunok_the_behemothAI: public ScriptedAI {
		npc_khunok_the_behemothAI(Creature* c) :
				ScriptedAI(c) {
		}

		void MoveInLineOfSight(Unit* who) {
			ScriptedAI::MoveInLineOfSight(who);

			if (who->GetTypeId() != TYPEID_UNIT)
				return;

			if (who->GetEntry() == 25861 && me->IsWithinDistInMap(who, 10.0f)) {
				if (Unit* owner = who->GetOwner()) {
					if (owner->GetTypeId() == TYPEID_PLAYER) {
						owner->CastSpell(owner, 46231, true);
						CAST_CRE(who)->DespawnOrUnsummon();
					}
				}
			}
		}
	};

	CreatureAI* GetAI(Creature* creature) const {
		return new npc_khunok_the_behemothAI(creature);
	}
};

/*######
 ## npc_keristrasza
 ######*/

enum eKeristrasza {
	SPELL_TELEPORT_TO_SARAGOSA = 46772
};

#define GOSSIP_HELLO_KERI   "I am prepared to face Saragosa!"
#define GOSSIP_HELLO_KERI_COMPLETE "Take me back to Amber Ledge!"

class npc_keristrasza: public CreatureScript {
public:
	npc_keristrasza() :
			CreatureScript("npc_keristrasza") {
	}

	bool OnGossipHello(Player* player, Creature* creature) {
		if (creature->isQuestGiver())
			player->PrepareQuestMenu(creature->GetGUID());

		if (player->GetQuestStatus(11957) == QUEST_STATUS_INCOMPLETE)
			player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_KERI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);

		if (player->GetQuestStatus(11957) == QUEST_STATUS_COMPLETE)
			player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_KERI_COMPLETE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);

		player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());

		return true;
	}

	bool OnGossipSelect(Player* player, Creature* /*creature*/,
			uint32 /*uiSender*/, uint32 uiAction) {
		player->PlayerTalkClass->ClearMenus();
		if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) {
			player->CLOSE_GOSSIP_MENU();
			player->CastSpell(player, SPELL_TELEPORT_TO_SARAGOSA, true);
		}

		if (uiAction == GOSSIP_ACTION_INFO_DEF + 2) {
			player->CLOSE_GOSSIP_MENU();
			player->TeleportTo(571, 3600.0f, 5955.0f, 136.2f, 0);
		}

		return true;
	}
};

/*######
 ## npc_corastrasza
 ######*/

#define GOSSIP_ITEM_C_1 "I... I think so..."

enum eCorastrasza {
	SPELL_SUMMON_WYRMREST_SKYTALON = 61240,
	SPELL_WYRMREST_SKYTALON_RIDE_PERIODIC = 61244,

	QUEST_ACES_HIGH_DAILY = 13414,
	QUEST_ACES_HIGH = 13413
};

class npc_corastrasza: public CreatureScript {
public:
	npc_corastrasza() :
			CreatureScript("npc_corastrasza") {
	}

	bool OnGossipHello(Player* player, Creature* creature) {
		if (creature->isQuestGiver())
			player->PrepareQuestMenu(creature->GetGUID());

		if (player->GetQuestStatus(QUEST_ACES_HIGH) == QUEST_STATUS_INCOMPLETE
				|| player->GetQuestStatus(QUEST_ACES_HIGH_DAILY)
						== QUEST_STATUS_INCOMPLETE) //It's the same dragon for both quests.
			player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_C_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);

		player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
		return true;
	}

	bool OnGossipSelect(Player* player, Creature* /*creature*/,
			uint32 /*uiSender*/, uint32 uiAction) {
		player->PlayerTalkClass->ClearMenus();
		if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) {
			player->CLOSE_GOSSIP_MENU();

			player->CastSpell(player, SPELL_SUMMON_WYRMREST_SKYTALON, true);
			player->CastSpell(player, SPELL_WYRMREST_SKYTALON_RIDE_PERIODIC,
					true);
		}

		return true;
	}
};

/*######
 ## vehicle_wyrmrest_skytalon
 ######*/

class vehicle_wyrmrest_skytalon: public CreatureScript {
public:
	vehicle_wyrmrest_skytalon() :
			CreatureScript("vehicle_wyrmrest_skytalon") {
	}

	struct vehicle_wyrmrest_skytalonAI: public VehicleAI {
		vehicle_wyrmrest_skytalonAI(Creature *c) :
				VehicleAI(c) {
		}

		uint32 check_Timer;
		bool isInUse;

		void Reset() {
			check_Timer = 6000;
		}

		void OnCharmed(bool apply) {
			isInUse = apply;

			if (!apply)
				check_Timer = 30000;
		}

		void UpdateAI(const uint32 diff) {
			if (!me->IsVehicle())
				return;

			if (!isInUse) {
				if (check_Timer < diff) {
					me->DealDamage(me, me->GetHealth());
					check_Timer = 6000;
				} else
					check_Timer -= diff;
			}
		}
	};

	CreatureAI* GetAI(Creature *_Creature) const {
		return new vehicle_wyrmrest_skytalonAI(_Creature);
	}
};

/*######
 ## npc_iruk
 ######*/

#define GOSSIP_ITEM_I  "<Search corpse for Issliruk's Totem.>"

enum eIruk {
	QUEST_SPIRITS_WATCH_OVER_US = 11961,
	SPELL_CREATURE_TOTEM_OF_ISSLIRUK = 46816,
	GOSSIP_TEXT_I = 12585
};

class npc_iruk: public CreatureScript {
public:
	npc_iruk() :
			CreatureScript("npc_iruk") {
	}

	bool OnGossipHello(Player* player, Creature* creature) {
		if (player->GetQuestStatus(QUEST_SPIRITS_WATCH_OVER_US)
				== QUEST_STATUS_INCOMPLETE)
			player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_I, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);

		player->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_I,
				creature->GetGUID());
		return true;
	}

	bool OnGossipSelect(Player* player, Creature* /*creature*/,
			uint32 /*uiSender*/, uint32 uiAction) {
		player->PlayerTalkClass->ClearMenus();
		switch (uiAction) {
		case GOSSIP_ACTION_INFO_DEF + 1:
			player->CastSpell(player, SPELL_CREATURE_TOTEM_OF_ISSLIRUK, true);
			player->CLOSE_GOSSIP_MENU();
			break;
		}
		return true;
	}
};

/*######
 ## mob_nerubar_victim
 ######*/

#define WARSONG_PEON        25270

const uint32 nerubarVictims[3] = { 45526, 45527, 45514 };

class mob_nerubar_victim: public CreatureScript {
public:
	mob_nerubar_victim() :
			CreatureScript("mob_nerubar_victim") {
	}

	struct mob_nerubar_victimAI: public ScriptedAI {
		mob_nerubar_victimAI(Creature* c) :
				ScriptedAI(c) {
		}

		void Reset() {
		}
		void EnterCombat(Unit* /*who*/) {
		}
		void MoveInLineOfSight(Unit* /*who*/) {
		}

		void JustDied(Unit* Killer) {
			if (Killer->GetTypeId() == TYPEID_PLAYER) {
				if (CAST_PLR(Killer)->GetQuestStatus(11611)
						== QUEST_STATUS_INCOMPLETE) {
					uint8 uiRand = urand(0, 99);
					if (uiRand < 25) {
						Killer->CastSpell(me, 45532, true);
						CAST_PLR(Killer)->KilledMonsterCredit(WARSONG_PEON, 0);
					} else if (uiRand < 75)
						Killer->CastSpell(me, nerubarVictims[urand(0, 2)],
								true);
				}
			}
		}
	};

	CreatureAI* GetAI(Creature* creature) const {
		return new mob_nerubar_victimAI(creature);
	}
};

/*######
 ## npc_scourge_prisoner
 ######*/

enum eScourgePrisoner {
	GO_SCOURGE_CAGE = 187867
};

class npc_scourge_prisoner: public CreatureScript {
public:
	npc_scourge_prisoner() :
			CreatureScript("npc_scourge_prisoner") {
	}

	struct npc_scourge_prisonerAI: public ScriptedAI {
		npc_scourge_prisonerAI(Creature* creature) :
				ScriptedAI(creature) {
		}

		void Reset() {
			me->SetReactState(REACT_PASSIVE);

			if (GameObject* pGO = me->FindNearestGameObject(GO_SCOURGE_CAGE, 5.0f))
				if (pGO->GetGoState() == GO_STATE_ACTIVE)
					pGO->SetGoState(GO_STATE_READY);
		}
	};

	CreatureAI* GetAI(Creature* creature) const {
		return new npc_scourge_prisonerAI(creature);
	}
};

/*######
 ## npc_jenny
 ######*/

enum eJenny {
	QUEST_LOADER_UP = 11881,

	NPC_FEZZIX_GEARTWIST = 25849,
	NPC_JENNY = 25969,

	SPELL_GIVE_JENNY_CREDIT = 46358,
	SPELL_CRATES_CARRIED = 46340,
	SPELL_DROP_CRATE = 46342
};

class npc_jenny: public CreatureScript {
public:
	npc_jenny() :
			CreatureScript("npc_jenny") {
	}

	struct npc_jennyAI: public ScriptedAI {
		npc_jennyAI(Creature* creature) :
				ScriptedAI(creature) {
		}

		bool setCrateNumber;

		void Reset() {
			if (!setCrateNumber)
				setCrateNumber = true;

			me->SetReactState(REACT_PASSIVE);

			switch (CAST_PLR(me->GetOwner())->GetTeamId()) {
			case TEAM_ALLIANCE:
				me->setFaction(FACTION_ESCORT_A_NEUTRAL_ACTIVE);
				break;
			default:
			case TEAM_HORDE:
				me->setFaction(FACTION_ESCORT_H_NEUTRAL_ACTIVE);
				break;
			}
		}

		void DamageTaken(Unit* /*pDone_by*/, uint32& /*uiDamage*/) {
			DoCast(me, SPELL_DROP_CRATE, true);
		}

		void UpdateAI(const uint32 /*diff*/) {
			if (setCrateNumber) {
				me->AddAura(SPELL_CRATES_CARRIED, me);
				setCrateNumber = false;
			}

			if (!setCrateNumber && !me->HasAura(SPELL_CRATES_CARRIED))
				me->DisappearAndDie();

			if (!UpdateVictim())
				return;
		}
	};

	CreatureAI* GetAI(Creature* creature) const {
		return new npc_jennyAI(creature);
	}
};

/*######
 ## npc_fezzix_geartwist
 ######*/

class npc_fezzix_geartwist: public CreatureScript {
public:
	npc_fezzix_geartwist() :
			CreatureScript("npc_fezzix_geartwist") {
	}

	struct npc_fezzix_geartwistAI: public ScriptedAI {
		npc_fezzix_geartwistAI(Creature* creature) :
				ScriptedAI(creature) {
		}

		void MoveInLineOfSight(Unit* who) {
			ScriptedAI::MoveInLineOfSight(who);

			if (who->GetTypeId() != TYPEID_UNIT)
				return;

			if (who->GetEntry() == NPC_JENNY
					&& me->IsWithinDistInMap(who, 10.0f)) {
				if (Unit* owner = who->GetOwner()) {
					if (owner->GetTypeId() == TYPEID_PLAYER) {
						if (who->HasAura(SPELL_CRATES_CARRIED)) {
							owner->CastSpell(owner, SPELL_GIVE_JENNY_CREDIT,
									true); // Maybe is not working.
							CAST_PLR(owner)->CompleteQuest(QUEST_LOADER_UP);
							CAST_CRE(who)->DisappearAndDie();
						}
					}
				}
			}
		}
	};

	CreatureAI* GetAI(Creature* creature) const {
		return new npc_fezzix_geartwistAI(creature);
	}
};

/*######
 ## npc_nesingwary_trapper
 ######*/

enum eNesingwaryTrapper {
	GO_HIGH_QUALITY_FUR = 187983,

	GO_CARIBOU_TRAP_1 = 187982,
	GO_CARIBOU_TRAP_2 = 187995,
	GO_CARIBOU_TRAP_3 = 187996,
	GO_CARIBOU_TRAP_4 = 187997,
	GO_CARIBOU_TRAP_5 = 187998,
	GO_CARIBOU_TRAP_6 = 187999,
	GO_CARIBOU_TRAP_7 = 188000,
	GO_CARIBOU_TRAP_8 = 188001,
	GO_CARIBOU_TRAP_9 = 188002,
	GO_CARIBOU_TRAP_10 = 188003,
	GO_CARIBOU_TRAP_11 = 188004,
	GO_CARIBOU_TRAP_12 = 188005,
	GO_CARIBOU_TRAP_13 = 188006,
	GO_CARIBOU_TRAP_14 = 188007,
	GO_CARIBOU_TRAP_15 = 188008,

	SPELL_TRAPPED = 46104,
};

#define CaribouTrapsNum 15
const uint32 CaribouTraps[CaribouTrapsNum] = { GO_CARIBOU_TRAP_1,
		GO_CARIBOU_TRAP_2, GO_CARIBOU_TRAP_3, GO_CARIBOU_TRAP_4,
		GO_CARIBOU_TRAP_5, GO_CARIBOU_TRAP_6, GO_CARIBOU_TRAP_7,
		GO_CARIBOU_TRAP_8, GO_CARIBOU_TRAP_9, GO_CARIBOU_TRAP_10,
		GO_CARIBOU_TRAP_11, GO_CARIBOU_TRAP_12, GO_CARIBOU_TRAP_13,
		GO_CARIBOU_TRAP_14, GO_CARIBOU_TRAP_15, };

class npc_nesingwary_trapper: public CreatureScript {
public:
	npc_nesingwary_trapper() :
			CreatureScript("npc_nesingwary_trapper") {
	}

	struct npc_nesingwary_trapperAI: public ScriptedAI {
		npc_nesingwary_trapperAI(Creature* c) :
				ScriptedAI(c) {
			c->SetVisible(false);
		}

		uint64 go_caribouGUID;
		uint8 Phase;
		uint32 uiPhaseTimer;

		void Reset() {
			me->SetVisible(false);
			uiPhaseTimer = 2500;
			Phase = 1;
			go_caribouGUID = 0;
		}
		void EnterCombat(Unit* /*who*/) {
		}
		void MoveInLineOfSight(Unit* /*who*/) {
		}

		void JustDied(Unit* /*who*/) {
			if (GameObject* go_caribou = me->GetMap()->GetGameObject(go_caribouGUID))
				go_caribou->SetLootState(GO_JUST_DEACTIVATED);

			if (TempSummon* summon = me->ToTempSummon())
				if (summon->isSummon())
					if (Unit* pTemp = summon->GetSummoner())
						if (pTemp->GetTypeId() == TYPEID_PLAYER)
							CAST_PLR(pTemp)->KilledMonsterCredit(me->GetEntry(),
									0);

			if (GameObject* go_caribou = me->GetMap()->GetGameObject(go_caribouGUID))
				go_caribou->SetGoState(GO_STATE_READY);
		}

		void UpdateAI(const uint32 diff) {
			if (uiPhaseTimer <= diff) {
				switch (Phase) {
				case 1:
					me->SetVisible(true);
					uiPhaseTimer = 2000;
					Phase = 2;
					break;

				case 2:
					if (GameObject* go_fur = me->FindNearestGameObject(GO_HIGH_QUALITY_FUR, 11.0f))
						me->GetMotionMaster()->MovePoint(0,
								go_fur->GetPositionX(), go_fur->GetPositionY(),
								go_fur->GetPositionZ());
					uiPhaseTimer = 1500;
					Phase = 3;
					break;
				case 3:
					//DoScriptText(SAY_NESINGWARY_1, me);
					uiPhaseTimer = 2000;
					Phase = 4;
					break;
				case 4:
					me->HandleEmoteCommand(EMOTE_ONESHOT_LOOT);
					uiPhaseTimer = 1000;
					Phase = 5;
					break;
				case 5:
					me->HandleEmoteCommand(EMOTE_ONESHOT_NONE);
					uiPhaseTimer = 500;
					Phase = 6;
					break;
				case 6:
					if (GameObject* go_fur = me->FindNearestGameObject(GO_HIGH_QUALITY_FUR, 11.0f))
						go_fur->Delete();
					uiPhaseTimer = 500;
					Phase = 7;
					break;

				case 7: {
					GameObject* go_caribou = NULL;
					for (uint8 i = 0; i < CaribouTrapsNum; ++i) {
						go_caribou = me->FindNearestGameObject(CaribouTraps[i],
								5.0f);
						if (go_caribou) {
							go_caribou->SetGoState(GO_STATE_ACTIVE);
							go_caribouGUID = go_caribou->GetGUID();
							break;
						}
					}
					Phase = 8;
					uiPhaseTimer = 1000;
				}
					break;
				case 8:
					DoCast(me, SPELL_TRAPPED, true);
					Phase = 0;
					break;
				}
			} else
				uiPhaseTimer -= diff;
		}
	};

	CreatureAI* GetAI(Creature* creature) const {
		return new npc_nesingwary_trapperAI(creature);
	}
};

/*######
 ## npc_lurgglbr
 ######*/

enum eLurgglbr {
	QUEST_ESCAPE_WINTERFIN_CAVERNS = 11570,

	GO_CAGE = 187369,

	FACTION_ESCORTEE_A = 774, FACTION_ESCORTEE_H = 775,
};

/*#define SAY_WP_1_LUR_START  -1571004
 #define SAY_WP_1_LUR_END    -1571005
 #define SAY_WP_41_LUR_START -1571006
 #define SAY_WP_41_LUR_END   -1571007*/

class npc_lurgglbr: public CreatureScript {
public:
	npc_lurgglbr() :
			CreatureScript("npc_lurgglbr") {
	}

	struct npc_lurgglbrAI: public npc_escortAI {
		npc_lurgglbrAI(Creature* creature) :
				npc_escortAI(creature) {
		}

		uint32 IntroTimer;
		uint32 IntroPhase;

		void Reset() {
			if (!HasEscortState(STATE_ESCORT_ESCORTING)) {
				IntroTimer = 0;
				IntroPhase = 0;
			}
		}

		void WaypointReached(uint32 i) {
			switch (i) {
			case 0:
				IntroPhase = 1;
				IntroTimer = 2000;
				break;
			case 41:
				IntroPhase = 4;
				IntroTimer = 2000;
				break;
			}
		}

		void UpdateAI(const uint32 diff) {
			if (IntroPhase) {
				if (IntroTimer <= diff) {
					switch (IntroPhase) {
					case 1:
						//DoScriptText(SAY_WP_1_LUR_START, me);
						IntroPhase = 2;
						IntroTimer = 7500;
						break;
					case 2:
						//DoScriptText(SAY_WP_1_LUR_END, me);
						IntroPhase = 3;
						IntroTimer = 7500;
						break;
					case 3:
						me->SetReactState(REACT_AGGRESSIVE);
						IntroPhase = 0;
						IntroTimer = 0;
						break;
					case 4:
						//DoScriptText(SAY_WP_41_LUR_START, me);
						IntroPhase = 5;
						IntroTimer = 8000;
						break;
					case 5:
						//DoScriptText(SAY_WP_41_LUR_END, me);
						IntroPhase = 6;
						IntroTimer = 2500;
						break;

					case 6:
						if (Player* player = GetPlayerForEscort())
							player->GroupEventHappens(
									QUEST_ESCAPE_WINTERFIN_CAVERNS, me);
						IntroPhase = 7;
						IntroTimer = 2500;
						break;

					case 7:
						me->DespawnOrUnsummon();
						IntroPhase = 0;
						IntroTimer = 0;
						break;
					}
				} else
					IntroTimer -= diff;
			}
			npc_escortAI::UpdateAI(diff);

			if (!UpdateVictim())
				return;
		}
	};

	CreatureAI* GetAI(Creature* creature) const {
		return new npc_lurgglbrAI(creature);
	}

	bool OnQuestAccept(Player* player, Creature* creature,
			Quest const* pQuest) {
		if (pQuest->GetQuestId() == QUEST_ESCAPE_WINTERFIN_CAVERNS) {
			if (GameObject* pGo = creature->FindNearestGameObject(GO_CAGE, 5.0f)) {
				pGo->SetRespawnTime(0);
				pGo->SetGoType(GAMEOBJECT_TYPE_BUTTON);
				pGo->UseDoorOrButton(20);
			}

			if (npc_escortAI* pEscortAI = CAST_AI(npc_lurgglbr::npc_lurgglbrAI, creature->AI()))
				pEscortAI->Start(true, false, player->GetGUID());

			switch (player->GetTeam()) {
			case ALLIANCE:
				creature->setFaction(FACTION_ESCORTEE_A);
				break;
			default:
			case HORDE:
				creature->setFaction(FACTION_ESCORTEE_H);
				break;
			}

			return true;
		}
		return false;
	}
};

/*######
 ## npc_nexus_drake_hatchling
 ######*/

enum eNexusDrakeHatchling {
	SPELL_DRAKE_HARPOON = 46607,
	SPELL_RED_DRAGONBLOOD = 46620,
	SPELL_DRAKE_HATCHLING_SUBDUED = 46691,
	SPELL_SUBDUED = 46675,

	NPC_RAELORASZ = 26117,

	QUEST_DRAKE_HUNT = 11919,
	QUEST_DRAKE_HUNT_D = 11940
};

class npc_nexus_drake_hatchling: public CreatureScript {
public:
	npc_nexus_drake_hatchling() :
			CreatureScript("npc_nexus_drake_hatchling") {
	}

	struct npc_nexus_drake_hatchlingAI: public FollowerAI //The spell who makes the npc follow the player is missing, also we can use FollowerAI!
	{
		npc_nexus_drake_hatchlingAI(Creature* c) :
				FollowerAI(c) {
		}

		uint64 HarpoonerGUID;
		bool WithRedDragonBlood;

		void Reset() {
			WithRedDragonBlood = false;
			HarpoonerGUID = 0;
		}

		void EnterCombat(Unit* who) {
			if (me->IsValidAttackTarget(who))
				AttackStart(who);
		}

		void SpellHit(Unit* caster, const SpellEntry* spell) {
			if (spell->Id == SPELL_DRAKE_HARPOON
					&& caster->GetTypeId() == TYPEID_PLAYER) {
				HarpoonerGUID = caster->GetGUID();
				DoCast(me, SPELL_RED_DRAGONBLOOD, true);
			}
			WithRedDragonBlood = true;
		}

		void MoveInLineOfSight(Unit* who) {
			FollowerAI::MoveInLineOfSight(who);

			if (!HarpoonerGUID)
				return;

			//This part isn't working correctcly
			/*if (me->HasAura(SPELL_SUBDUED) && who->GetEntry() == NPC_RAELORASZ)
			 {                if (me->IsWithinDistInMap(who, INTERACTION_DISTANCE))
			 {
			 if (Player* pHarpooner = Unit::GetPlayer(*me, HarpoonerGUID))
			 {
			 pHarpooner->KilledMonsterCredit(26175, 0);
			 pHarpooner->RemoveAura(SPELL_DRAKE_HATCHLING_SUBDUED);
			 SetFollowComplete();
			 HarpoonerGUID = 0;
			 me->DisappearAndDie();
			 }
			 }
			 }*/
		}

		void UpdateAI(const uint32 /*diff*/) {
			if (WithRedDragonBlood && HarpoonerGUID
					&& !me->HasAura(SPELL_RED_DRAGONBLOOD)) {
				if (Player* pHarpooner = Unit::GetPlayer(*me, HarpoonerGUID)) {
					EnterEvadeMode();
					StartFollow(pHarpooner, 35, NULL);

					DoCast(me, SPELL_SUBDUED, true);
					pHarpooner->CastSpell(pHarpooner,
							SPELL_DRAKE_HATCHLING_SUBDUED, true);

					me->AttackStop();
					WithRedDragonBlood = false;
				}
			}

			if (me->HasAura(SPELL_SUBDUED)) {
				if (Creature* pRaelorasz = me->FindNearestCreature(NPC_RAELORASZ, 10.0f)) {
					if (Player* pHarpooner = GetLeaderForFollower()) {
						pHarpooner->KilledMonsterCredit(26175, 0);
						pHarpooner->RemoveAura(SPELL_DRAKE_HATCHLING_SUBDUED);
						SetFollowComplete();
						HarpoonerGUID = 0;
						me->DisappearAndDie();
					}
				}
			}

			if (!UpdateVictim())
				return;

			DoMeleeAttackIfReady();
		}
	};

	CreatureAI* GetAI(Creature* creature) const {
		return new npc_nexus_drake_hatchlingAI(creature);
	}
};

/*######
 ## npc_thassarian
 ######*/

enum eThassarian {
	QUEST_LAST_RITES = 12019,

	SPELL_TRANSFORM_VALANAR = 46753,
	SPELL_STUN = 46957,
	SPELL_SHADOW_BOLT = 15537,

	NPC_IMAGE_LICH_KING = 26203,
	NPC_COUNSELOR_TALBOT = 25301,
	NPC_PRINCE_VALANAR = 28189,
	NPC_GENERAL_ARLOS = 25250,
	NPC_LERYSSA = 25251,

	SAY_TALBOT_1 = -1571004,
	SAY_LICH_1 = -1571005,
	SAY_TALBOT_2 = -1571006,
	SAY_THASSARIAN_1 = -1571007,
	SAY_THASSARIAN_2 = -1571008,
	SAY_LICH_2 = -1571009,
	SAY_THASSARIAN_3 = -1571010,
	SAY_TALBOT_3 = -1571011,
	SAY_LICH_3 = -1571012,
	SAY_TALBOT_4 = -1571013,
	SAY_ARLOS_1 = -1571014,
	SAY_ARLOS_2 = -1571015,
	SAY_LERYSSA_1 = -1571016,
	SAY_THASSARIAN_4 = -1571017,
	SAY_LERYSSA_2 = -1571018,
	SAY_THASSARIAN_5 = -1571019,
	SAY_LERYSSA_3 = -1571020,
	SAY_THASSARIAN_6 = -1571021,
	SAY_LERYSSA_4 = -1571022,
	SAY_THASSARIAN_7 = -1571023,
};

#define GOSSIP_ITEM_T   "Let's do this, Thassarian. It's now or never."

class npc_thassarian: public CreatureScript {
public:
	npc_thassarian() :
			CreatureScript("npc_thassarian") {
	}

	struct npc_thassarianAI: public npc_escortAI {
		npc_thassarianAI(Creature* creature) :
				npc_escortAI(creature) {
		}

		uint64 uiArthas;
		uint64 uiTalbot;
		uint64 uiLeryssa;
		uint64 uiArlos;

		bool bArthasInPosition;
		bool bArlosInPosition;
		bool bLeryssaInPosition;
		bool bTalbotInPosition;

		uint32 uiPhase;
		uint32 uiPhaseTimer;

		void Reset() {
			me->RestoreFaction();
			me->RemoveStandFlags(UNIT_STAND_STATE_SIT);

			uiArthas = 0;
			uiTalbot = 0;
			uiLeryssa = 0;
			uiArlos = 0;

			bArthasInPosition = false;
			bArlosInPosition = false;
			bLeryssaInPosition = false;
			bTalbotInPosition = false;

			uiPhase = 0;
			uiPhaseTimer = 0;
		}

		void WaypointReached(uint32 uiPointId) {
			Player* player = GetPlayerForEscort();

			if (!player)
				return;

			switch (uiPointId) {
			case 3:
				SetEscortPaused(true);
				if (Creature* pArthas = me->SummonCreature(NPC_IMAGE_LICH_KING, 3730.313f, 3518.689f, 473.324f, 1.562f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 120000)) {
					uiArthas = pArthas->GetGUID();
					pArthas->SetFlag(UNIT_FIELD_FLAGS,
							UNIT_FLAG_NON_ATTACKABLE);
					pArthas->SetReactState(REACT_PASSIVE);
					pArthas->AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
					pArthas->GetMotionMaster()->MovePoint(0, 3737.374756f,
							3564.841309f, 477.433014f);
				}
				if (Creature* pTalbot = me->SummonCreature(NPC_COUNSELOR_TALBOT, 3747.23f, 3614.936f, 473.321f, 4.462012f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 120000)) {
					uiTalbot = pTalbot->GetGUID();
					pTalbot->AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
					pTalbot->GetMotionMaster()->MovePoint(0, 3738.000977f,
							3568.882080f, 477.433014f);
				}
				me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
				break;

			case 4:
				SetEscortPaused(true);
				uiPhase = 7;
				break;
			}
		}

		void UpdateAI(const uint32 uiDiff) {
			npc_escortAI::UpdateAI(uiDiff);

			if (bArthasInPosition && bTalbotInPosition) {
				uiPhase = 1;
				bArthasInPosition = false;
				bTalbotInPosition = false;
			}

			if (bArlosInPosition && bLeryssaInPosition) {
				bArlosInPosition = false;
				bLeryssaInPosition = false;
				DoScriptText(SAY_THASSARIAN_1, me);
				SetEscortPaused(false);
			}

			if (uiPhaseTimer <= uiDiff) {
				Creature* pTalbot = me->GetCreature(*me, uiTalbot);
				Creature* pArthas = me->GetCreature(*me, uiArthas);
				switch (uiPhase) {
				case 1:
					if (pTalbot)
						pTalbot->SetStandState(UNIT_STAND_STATE_KNEEL);
					uiPhaseTimer = 3000;
					++uiPhase;
					break;

				case 2:
					if (pTalbot) {
						pTalbot->UpdateEntry(NPC_PRINCE_VALANAR, ALLIANCE);
						pTalbot->setFaction(14);
						pTalbot->SetFlag(UNIT_FIELD_FLAGS,
								UNIT_FLAG_NON_ATTACKABLE);
						pTalbot->SetReactState(REACT_PASSIVE);
					}
					uiPhaseTimer = 5000;
					++uiPhase;
					break;

				case 3:
					if (pTalbot)
						DoScriptText(SAY_TALBOT_1, pTalbot);
					uiPhaseTimer = 5000;
					++uiPhase;
					break;

				case 4:
					if (pArthas)
						DoScriptText(SAY_LICH_1, pArthas);
					uiPhaseTimer = 5000;
					++uiPhase;
					break;

				case 5:
					if (pTalbot)
						DoScriptText(SAY_TALBOT_2, pTalbot);
					uiPhaseTimer = 5000;
					++uiPhase;
					break;

				case 6:
					if (Creature* pArlos = me->SummonCreature(NPC_GENERAL_ARLOS, 3745.527100f, 3615.655029f, 473.321533f, 4.447805f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 120000)) {
						uiArlos = pArlos->GetGUID();
						pArlos->AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
						pArlos->GetMotionMaster()->MovePoint(0, 3735.570068f,
								3572.419922f, 477.441010f);
					}
					if (Creature* pLeryssa = me->SummonCreature(NPC_LERYSSA, 3749.654541f, 3614.959717f, 473.323486f, 4.524959f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 120000)) {
						uiLeryssa = pLeryssa->GetGUID();
						pLeryssa->AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
						pLeryssa->SetReactState(REACT_PASSIVE);
						pLeryssa->SetFlag(UNIT_FIELD_FLAGS,
								UNIT_FLAG_NON_ATTACKABLE);
						pLeryssa->GetMotionMaster()->MovePoint(0, 3741.969971f,
								3571.439941f, 477.441010f);
					}
					uiPhaseTimer = 2000;
					uiPhase = 0;
					break;

				case 7:
					DoScriptText(SAY_THASSARIAN_2, me);
					uiPhaseTimer = 5000;
					++uiPhase;
					break;

				case 8:
					if (pArthas && pTalbot) {
						pArthas->SetInFront(me); //The client doesen't update with the new orientation :l
						pTalbot->SetStandState(UNIT_STAND_STATE_STAND);
						DoScriptText(SAY_LICH_2, pArthas);
					}
					uiPhaseTimer = 5000;
					uiPhase = 9;
					break;

				case 9:
					DoScriptText(SAY_THASSARIAN_3, me);
					uiPhaseTimer = 5000;
					uiPhase = 10;
					break;

				case 10:
					if (pTalbot)
						DoScriptText(SAY_TALBOT_3, pTalbot);
					uiPhaseTimer = 5000;
					uiPhase = 11;
					break;

				case 11:
					if (pArthas)
						DoScriptText(SAY_LICH_3, pArthas);
					uiPhaseTimer = 5000;
					uiPhase = 12;
					break;

				case 12:
					if (pTalbot)
						DoScriptText(SAY_TALBOT_4, pTalbot);
					uiPhaseTimer = 2000;
					uiPhase = 13;
					break;

				case 13:
					if (pArthas)
						pArthas->RemoveFromWorld();
					++uiPhase;
					break;

				case 14:
					me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
					if (pTalbot) {
						pTalbot->RemoveFlag(UNIT_FIELD_FLAGS,
								UNIT_FLAG_NON_ATTACKABLE);
						pTalbot->SetReactState(REACT_AGGRESSIVE);
						pTalbot->CastSpell(me, SPELL_SHADOW_BOLT, false);
					}
					uiPhaseTimer = 1500;
					++uiPhase;
					break;

				case 15:
					me->SetReactState(REACT_AGGRESSIVE);
					AttackStart(pTalbot);
					uiPhase = 0;
					break;

				case 16:
					me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
					uiPhaseTimer = 20000;
					++uiPhase;
					break;

				case 17:
					if (Creature* pLeryssa = me->GetCreature(*me, uiLeryssa))
						pLeryssa->RemoveFromWorld();
					if (Creature* pArlos= me->GetCreature(*me, uiArlos))
						pArlos->RemoveFromWorld();
					if (pTalbot)
						pTalbot->RemoveFromWorld();
					me->RemoveStandFlags(UNIT_STAND_STATE_SIT);
					SetEscortPaused(false);
					uiPhaseTimer = 0;
					uiPhase = 0;
				}
			} else
				uiPhaseTimer -= uiDiff;

			if (!UpdateVictim())
				return;

			DoMeleeAttackIfReady();
		}

		void JustDied(Unit* /*killer*/) {
			if (Creature* pTalbot = me->GetCreature(*me, uiTalbot))
				pTalbot->RemoveFromWorld();

			if (Creature* pLeryssa = me->GetCreature(*me, uiLeryssa))
				pLeryssa->RemoveFromWorld();

			if (Creature* pArlos = me->GetCreature(*me, uiArlos))
				pArlos->RemoveFromWorld();

			if (Creature* pArthas = me->GetCreature(*me, uiArthas))
				pArthas->RemoveFromWorld();
		}
	};

	bool OnGossipHello(Player* player, Creature* creature) {
		if (creature->isQuestGiver())
			player->PrepareQuestMenu(creature->GetGUID());

		if (player->GetQuestStatus(QUEST_LAST_RITES) == QUEST_STATUS_INCOMPLETE
				&& creature->GetAreaId() == 4128)
			player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_T, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);

		player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());

		return true;
	}

	bool OnGossipSelect(Player* player, Creature* creature, uint32 /*uiSender*/,
			uint32 uiAction) {
		player->PlayerTalkClass->ClearMenus();
		switch (uiAction) {
		case GOSSIP_ACTION_INFO_DEF + 1:
			CAST_AI(npc_escortAI, (creature->AI()))->Start(true, false,
					player->GetGUID());
			CAST_AI(npc_escortAI, (creature->AI()))->SetMaxPlayerDistance(
					200.0f);
			break;
		}
		return true;
	}

	CreatureAI* GetAI(Creature* creature) const {
		return new npc_thassarianAI(creature);
	}
};

/*######
 ## npc_image_lich_king
 ######*/

class npc_image_lich_king: public CreatureScript {
public:
	npc_image_lich_king() :
			CreatureScript("npc_image_lich_king") {
	}

	struct npc_image_lich_kingAI: public ScriptedAI {
		npc_image_lich_kingAI(Creature* creature) :
				ScriptedAI(creature) {
		}

		void Reset() {
			me->RestoreFaction();
		}

		void MovementInform(uint32 uiType, uint32 /*uiId*/) {
			if (uiType != POINT_MOTION_TYPE)
				return;

			if (me->isSummon())
				if (Unit* summoner = me->ToTempSummon()->GetSummoner())
					CAST_AI(npc_thassarian::npc_thassarianAI, CAST_CRE(summoner)->AI())->bArthasInPosition =
							true;
		}
	};

	CreatureAI* GetAI(Creature* creature) const {
		return new npc_image_lich_kingAI(creature);
	}
};

/*######
 ## npc_general_arlos
 ######*/

class npc_general_arlos: public CreatureScript {
public:
	npc_general_arlos() :
			CreatureScript("npc_general_arlos") {
	}

	struct npc_general_arlosAI: public ScriptedAI {
		npc_general_arlosAI(Creature* creature) :
				ScriptedAI(creature) {
		}

		void MovementInform(uint32 uiType, uint32 /*uiId*/) {
			if (uiType != POINT_MOTION_TYPE)
				return;

			me->AddUnitState(UNIT_STAT_STUNNED);
			me->CastSpell(me, SPELL_STUN, true);
			if (me->isSummon())
				if (Unit* summoner = me->ToTempSummon()->GetSummoner())
					CAST_AI(npc_thassarian::npc_thassarianAI, CAST_CRE(summoner)->AI())->bArlosInPosition =
							true;
		}
	};

	CreatureAI* GetAI(Creature* creature) const {
		return new npc_general_arlosAI(creature);
	}
};

/*######
 ## npc_counselor_talbot
 ######*/

enum eCounselorTalbot {
	SPELL_DEFLECTION = 51009, SPELL_SOUL_BLAST = 50992,
};

class npc_counselor_talbot: public CreatureScript {
public:
	npc_counselor_talbot() :
			CreatureScript("npc_counselor_talbot") {
	}

	struct npc_counselor_talbotAI: public ScriptedAI {
		npc_counselor_talbotAI(Creature* creature) :
				ScriptedAI(creature) {
			creature->RestoreFaction();
		}

		uint64 LeryssaGUID;
		uint64 ArlosGUID;

		bool bCheck;

		uint32 uiShadowBoltTimer;
		uint32 uiDeflectionTimer;
		uint32 uiSoulBlastTimer;

		void Reset() {
			LeryssaGUID = 0;
			ArlosGUID = 0;
			bCheck = false;
			uiShadowBoltTimer = urand(5000, 12000);
			uiDeflectionTimer = urand(20000, 25000);
			uiSoulBlastTimer = urand(12000, 18000);
		}
		void MovementInform(uint32 uiType, uint32 /*uiId*/) {
			if (uiType != POINT_MOTION_TYPE)
				return;

			if (me->isSummon())
				if (Unit* summoner = me->ToTempSummon()->GetSummoner())
					CAST_AI(npc_thassarian::npc_thassarianAI, CAST_CRE(summoner)->AI())->bTalbotInPosition =
							true;
		}

		void UpdateAI(const uint32 uiDiff) {
			if (bCheck) {
				if (Creature* pLeryssa = me->FindNearestCreature(NPC_LERYSSA, 50.0f, true))
					LeryssaGUID = pLeryssa->GetGUID();
				if (Creature* pArlos = me->FindNearestCreature(NPC_GENERAL_ARLOS, 50.0f, true))
					ArlosGUID = pArlos->GetGUID();
				bCheck = false;
			}

			if (!UpdateVictim())
				return;

			if (me->GetAreaId() == 4128) {
				if (uiShadowBoltTimer <= uiDiff) {
					DoCast(me->getVictim(), SPELL_SHADOW_BOLT);
					uiShadowBoltTimer = urand(5000, 12000);
				} else
					uiShadowBoltTimer -= uiDiff;

				if (uiDeflectionTimer <= uiDiff) {
					DoCast(me->getVictim(), SPELL_DEFLECTION);
					uiDeflectionTimer = urand(20000, 25000);
				} else
					uiDeflectionTimer -= uiDiff;

				if (uiSoulBlastTimer <= uiDiff) {
					DoCast(me->getVictim(), SPELL_SOUL_BLAST);
					uiSoulBlastTimer = urand(12000, 18000);
				} else
					uiSoulBlastTimer -= uiDiff;
			}

			DoMeleeAttackIfReady();
		}

		void JustDied(Unit* killer) {
			if (!LeryssaGUID || !ArlosGUID)
				return;

			Creature* pLeryssa = Unit::GetCreature(*me, LeryssaGUID);
			Creature* pArlos = Unit::GetCreature(*me, ArlosGUID);
			if (!pLeryssa || !pArlos)
				return;

			DoScriptText(SAY_ARLOS_1, pArlos);
			DoScriptText(SAY_ARLOS_2, pArlos);
			DoScriptText(SAY_LERYSSA_1, pLeryssa);
			pArlos->Kill(pArlos, false);
			pLeryssa->RemoveAura(SPELL_STUN);
			pLeryssa->ClearUnitState(UNIT_STAT_STUNNED);
			pLeryssa->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
			pLeryssa->GetMotionMaster()->MovePoint(0, 3722.114502f,
					3564.201660f, 477.441437f);

			if (killer->GetTypeId() == TYPEID_PLAYER)
				CAST_PLR(killer)->RewardPlayerAndGroupAtEvent(
						NPC_PRINCE_VALANAR, 0);
		}
	};

	CreatureAI* GetAI(Creature* creature) const {
		return new npc_counselor_talbotAI(creature);
	}
};

/*######
 ## npc_leryssa
 ######*/

class npc_leryssa: public CreatureScript {
public:
	npc_leryssa() :
			CreatureScript("npc_leryssa") {
	}

	struct npc_leryssaAI: public ScriptedAI {
		npc_leryssaAI(Creature* creature) :
				ScriptedAI(creature) {
			bDone = false;
			Phase = 0;
			uiPhaseTimer = 0;

			creature->RemoveStandFlags(UNIT_STAND_STATE_SIT);
		}

		bool bDone;

		uint32 Phase;
		uint32 uiPhaseTimer;

		void MovementInform(uint32 uiType, uint32 /*uiId*/) {
			if (uiType != POINT_MOTION_TYPE)
				return;

			if (!bDone) {
				if (Creature* pTalbot = me->FindNearestCreature(NPC_PRINCE_VALANAR, 50.0f, true))
					CAST_AI(npc_counselor_talbot::npc_counselor_talbotAI, pTalbot->GetAI())->bCheck =
							true;

				me->AddUnitState(UNIT_STAT_STUNNED);
				me->CastSpell(me, SPELL_STUN, true);

				if (me->isSummon())
					if (Unit* summoner = me->ToTempSummon()->GetSummoner())
						CAST_AI(npc_thassarian::npc_thassarianAI, summoner->GetAI())->bLeryssaInPosition =
								true;
				bDone = true;
			} else {
				me->SetStandState(UNIT_STAND_STATE_SIT);
				if (me->isSummon())
					if (Unit* summoner = me->ToTempSummon()->GetSummoner())
						summoner->SetStandState(UNIT_STAND_STATE_SIT);
				uiPhaseTimer = 1500;
				Phase = 1;
			}
		}

		void UpdateAI(const uint32 uiDiff) {
			ScriptedAI::UpdateAI(uiDiff);

			if (uiPhaseTimer <= uiDiff) {
				switch (Phase) {
				case 1:
					if (me->isSummon())
						if (Unit* pThassarian = me->ToTempSummon()->GetSummoner())
							DoScriptText(SAY_THASSARIAN_4, pThassarian);
					uiPhaseTimer = 5000;
					++Phase;
					break;
				case 2:
					DoScriptText(SAY_LERYSSA_2, me);
					uiPhaseTimer = 5000;
					++Phase;
					break;
				case 3:
					if (me->isSummon())
						if (Unit* pThassarian = me->ToTempSummon()->GetSummoner())
							DoScriptText(SAY_THASSARIAN_5, pThassarian);
					uiPhaseTimer = 5000;
					++Phase;
					break;
				case 4:
					DoScriptText(SAY_LERYSSA_3, me);
					uiPhaseTimer = 5000;
					++Phase;
					break;
				case 5:
					if (me->isSummon())
						if (Unit* pThassarian = me->ToTempSummon()->GetSummoner())
							DoScriptText(SAY_THASSARIAN_6, pThassarian);
					uiPhaseTimer = 5000;
					++Phase;
					break;

				case 6:
					DoScriptText(SAY_LERYSSA_4, me);
					uiPhaseTimer = 5000;
					++Phase;
					break;
				case 7:
					if (me->isSummon())
						if (Unit* pThassarian = me->ToTempSummon()->GetSummoner()) {
							DoScriptText(SAY_THASSARIAN_7, pThassarian);
							CAST_AI(npc_thassarian::npc_thassarianAI, pThassarian->GetAI())->uiPhase =
									16;
						}
					uiPhaseTimer = 5000;
					Phase = 0;
					break;
				}
			} else
				uiPhaseTimer -= uiDiff;

			if (!UpdateVictim())
				return;

			DoMeleeAttackIfReady();
		}
	};

	CreatureAI* GetAI(Creature* creature) const {
		return new npc_leryssaAI(creature);
	}
};

/*######
 ## npc_beryl_sorcerer
 ######*/

enum eBerylSorcerer {
	NPC_CAPTURED_BERLY_SORCERER = 25474,
	NPC_LIBRARIAN_DONATHAN = 25262,

	SPELL_ARCANE_CHAINS = 45611,
	SPELL_COSMETIC_CHAINS = 54324,
	SPELL_COSMETIC_ENSLAVE_CHAINS_SELF = 45631
};

class npc_beryl_sorcerer: public CreatureScript {
public:
	npc_beryl_sorcerer() :
			CreatureScript("npc_beryl_sorcerer") {
	}

	struct npc_beryl_sorcererAI: public FollowerAI {
		npc_beryl_sorcererAI(Creature* creature) :
				FollowerAI(creature) {
		}

		bool bEnslaved;

		void Reset() {
			me->SetReactState(REACT_AGGRESSIVE);
			bEnslaved = false;
		}

		void EnterCombat(Unit* who) {
			if (me->IsValidAttackTarget(who))
				AttackStart(who);
		}

		void SpellHit(Unit* pCaster, const SpellEntry* pSpell) {
			if (pSpell->Id == SPELL_ARCANE_CHAINS
					&& pCaster->GetTypeId() == TYPEID_PLAYER
					&& !HealthAbovePct(50) && !bEnslaved) {
				EnterEvadeMode(); //We make sure that the npc is not attacking the player!
				me->SetReactState(REACT_PASSIVE);
				StartFollow(pCaster->ToPlayer(), 0, NULL);
				me->UpdateEntry(NPC_CAPTURED_BERLY_SORCERER, TEAM_NEUTRAL);
				DoCast(me, SPELL_COSMETIC_ENSLAVE_CHAINS_SELF, true);
				CAST_PLR(pCaster)->KilledMonsterCredit(
						NPC_CAPTURED_BERLY_SORCERER, 0);
				bEnslaved = true;
			}
		}

		void MoveInLineOfSight(Unit* who) {
			FollowerAI::MoveInLineOfSight(who);

			if (who->GetEntry() == NPC_LIBRARIAN_DONATHAN
					&& me->IsWithinDistInMap(who, INTERACTION_DISTANCE)) {
				SetFollowComplete();
				me->DisappearAndDie();
			}
		}

		void UpdateAI(const uint32 /*uiDiff*/) {
			if (!UpdateVictim())
				return;

			DoMeleeAttackIfReady();
		}
	};

	CreatureAI* GetAI(Creature* creature) const {
		return new npc_beryl_sorcererAI(creature);
	}
};

/*######
 ## npc_imprisoned_beryl_sorcerer
 ######*/

enum eImprisionedBerylSorcerer {
	SPELL_NEURAL_NEEDLE = 45634,

	NPC_IMPRISONED_BERYL_SORCERER = 25478,

	SAY_IMPRISIONED_BERYL_1 = -1571024,
	SAY_IMPRISIONED_BERYL_2 = -1571025,
	SAY_IMPRISIONED_BERYL_3 = -1571026,
	SAY_IMPRISIONED_BERYL_4 = -1571027,
	SAY_IMPRISIONED_BERYL_5 = -1571028,
	SAY_IMPRISIONED_BERYL_6 = -1571029,
	SAY_IMPRISIONED_BERYL_7 = -1571030,
};

class npc_imprisoned_beryl_sorcerer: public CreatureScript {
public:
	npc_imprisoned_beryl_sorcerer() :
			CreatureScript("npc_imprisoned_beryl_sorcerer") {
	}

	struct npc_imprisoned_beryl_sorcererAI: public ScriptedAI {
		npc_imprisoned_beryl_sorcererAI(Creature* creature) :
				ScriptedAI(creature) {
		}

		uint64 CasterGUID;

		uint32 uiStep;
		uint32 uiPhase;

		void Reset() {
			uiStep = 1;
			uiPhase = 0;
			CasterGUID = 0;
		}

		void EnterCombat(Unit* /*who*/) {
		}

		void SpellHit(Unit* pUnit, const SpellEntry* pSpell) {
			if (pSpell->Id == SPELL_NEURAL_NEEDLE
					&& pUnit->GetTypeId() == TYPEID_PLAYER) {
				++uiPhase;
				CasterGUID = pUnit->GetGUID();
			}
		}

		void UpdateAI(const uint32 uiDiff) {
			ScriptedAI::UpdateAI(uiDiff);

			if (!me->HasAura(SPELL_COSMETIC_ENSLAVE_CHAINS_SELF))
				DoCast(me, SPELL_COSMETIC_ENSLAVE_CHAINS_SELF);

			if (me->GetReactState() != REACT_PASSIVE)
				me->SetReactState(REACT_PASSIVE);

			switch (uiPhase) {
			case 1:
				if (uiStep == 1) {
					DoScriptText(SAY_IMPRISIONED_BERYL_1, me);
					uiStep = 2;
				}
				break;

			case 2:
				if (uiStep == 2) {
					DoScriptText(SAY_IMPRISIONED_BERYL_2, me);
					uiStep = 3;
				}
				break;

			case 3:
				if (uiStep == 3) {
					DoScriptText(SAY_IMPRISIONED_BERYL_3, me);
					uiStep = 4;
				}
				break;

			case 4:
				if (uiStep == 4) {
					DoScriptText(SAY_IMPRISIONED_BERYL_4, me);
					uiStep = 5;
				}
				break;

			case 5:
				if (uiStep == 5) {
					if (Player* pCaster = Unit::GetPlayer(*me, CasterGUID)) {
						DoScriptText(SAY_IMPRISIONED_BERYL_5, me);
						pCaster->KilledMonsterCredit(25478, 0);
						uiStep = 6;
					}
				}
				break;

			case 6:
				if (uiStep == 6) {
					DoScriptText(SAY_IMPRISIONED_BERYL_6, me);
					uiStep = 7;
				}
				break;

			case 7:
				if (uiStep == 7) {
					DoScriptText(SAY_IMPRISIONED_BERYL_7, me);
					uiStep = 1;
					uiPhase = 0;
				}
				break;
			}
		}
	};

	CreatureAI* GetAI(Creature* creature) const {
		return new npc_imprisoned_beryl_sorcererAI(creature);
	}
};

/*######
 ## npc_mootoo_the_younger
 ######*/
enum Script_Texts_Mootoo_the_Younger {
	SAY_1 = -1750040,
	SAY_2 = -1750041,
	SAY_3 = -1750042,
	SAY_4 = -1750043,
	SAY_5 = -1750044
};
enum Mootoo_the_Younger_Entries {
	NPC_MOOTOO_THE_YOUNGER = 25504, QUEST_ESCAPING_THE_MIST = 11664
};

class npc_mootoo_the_younger: public CreatureScript {
public:
	npc_mootoo_the_younger() :
			CreatureScript("npc_mootoo_the_younger") {
	}

	bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest) {
		if (quest->GetQuestId() == QUEST_ESCAPING_THE_MIST) {
			switch (player->GetTeam()) {
			case ALLIANCE:
				creature->setFaction(FACTION_ESCORTEE_A);
				break;
			case HORDE:
				creature->setFaction(FACTION_ESCORTEE_H);
				break;
			}
			creature->SetStandState(UNIT_STAND_STATE_STAND);
			DoScriptText(SAY_1, creature);
			CAST_AI(npc_escortAI, (creature->AI()))->Start(true, false,
					player->GetGUID());
		}
		return true;
	}

	struct npc_mootoo_the_youngerAI: public npc_escortAI {
		npc_mootoo_the_youngerAI(Creature* c) :
				npc_escortAI(c) {
		}

		void Reset() {
			SetDespawnAtFar(false);
		}

		void JustDied(Unit* /*killer*/) {
			if (Player* player=GetPlayerForEscort())
				player->FailQuest(QUEST_ESCAPING_THE_MIST);
		}

		void WaypointReached(uint32 i) {
			Player* player = GetPlayerForEscort();

			if (!player)
				return;

			switch (i) {
			case 10:
				me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION);
				DoScriptText(SAY_2, me);
				break;
			case 12:
				DoScriptText(SAY_3, me);
				me->HandleEmoteCommand(EMOTE_ONESHOT_LOOT);
				break;
			case 16:
				DoScriptText(SAY_4, me);
				me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION);
				break;
			case 20:
				me->SetPhaseMask(1, true);
				DoScriptText(SAY_5, me);
				me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION);
				if (player)
					player->GroupEventHappens(QUEST_ESCAPING_THE_MIST, me);
				SetRun(true);
				break;
			}
		}
	};

	CreatureAI* GetAI(Creature* creature) const {
		return new npc_mootoo_the_youngerAI(creature);
	}
};

/*######
 ## npc_bonker_togglevolt
 ######*/

enum Bonker_Togglevolt_Entries {
	NPC_BONKER_TOGGLEVOLT = 25589, QUEST_GET_ME_OUTA_HERE = 11673
};
enum Script_Texts_Bonker_Togglevolt {
	SAY_bonker_1 = -1700002, SAY_bonker_2 = -1700003
};

class npc_bonker_togglevolt: public CreatureScript {
public:
	npc_bonker_togglevolt() :
			CreatureScript("npc_bonker_togglevolt") {
	}

	bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest) {
		if (quest->GetQuestId() == QUEST_GET_ME_OUTA_HERE) {
			creature->SetStandState(UNIT_STAND_STATE_STAND);
			DoScriptText(SAY_bonker_2, creature, player);
			CAST_AI(npc_escortAI, (creature->AI()))->Start(true, true,
					player->GetGUID());
		}
		return true;
	}

	struct npc_bonker_togglevoltAI: public npc_escortAI {
		npc_bonker_togglevoltAI(Creature* c) :
				npc_escortAI(c) {
		}
		uint32 Bonker_agro;

		void Reset() {
			Bonker_agro = 0;
			SetDespawnAtFar(false);
		}

		void JustDied(Unit* /*killer*/) {
			if (Player* player = GetPlayerForEscort())
				player->FailQuest(QUEST_GET_ME_OUTA_HERE);
		}

		void UpdateEscortAI(const uint32 /*diff*/) {
			if (GetAttack() && UpdateVictim()) {
				if (Bonker_agro == 0) {
					DoScriptText(SAY_bonker_1, me);
					Bonker_agro++;
				}
				DoMeleeAttackIfReady();
			} else
				Bonker_agro = 0;
		}

		void WaypointReached(uint32 i) {
			Player* player = GetPlayerForEscort();

			if (!player)
				return;

			switch (i) {
			case 29:
				if (player)
					player->GroupEventHappens(QUEST_GET_ME_OUTA_HERE, me);
				break;
			}
		}
	};

	CreatureAI* GetAI(Creature* creature) const {
		return new npc_bonker_togglevoltAI(creature);
	}
};

/*######
 ## Help Those That Cannot Help Themselves, Quest 11876
 ######*/

enum eHelpThemselves {
	QUEST_CANNOT_HELP_THEMSELVES = 11876,
	GO_MAMMOTH_TRAP_1 = 188022,
	GO_MAMMOTH_TRAP_2 = 188024,
	GO_MAMMOTH_TRAP_3 = 188025,
	GO_MAMMOTH_TRAP_4 = 188026,
	GO_MAMMOTH_TRAP_5 = 188027,
	GO_MAMMOTH_TRAP_6 = 188028,
	GO_MAMMOTH_TRAP_7 = 188029,
	GO_MAMMOTH_TRAP_8 = 188030,
	GO_MAMMOTH_TRAP_9 = 188031,
	GO_MAMMOTH_TRAP_10 = 188032,
	GO_MAMMOTH_TRAP_11 = 188033,
	GO_MAMMOTH_TRAP_12 = 188034,
	GO_MAMMOTH_TRAP_13 = 188035,
	GO_MAMMOTH_TRAP_14 = 188036,
	GO_MAMMOTH_TRAP_15 = 188037,
	GO_MAMMOTH_TRAP_16 = 188038,
	GO_MAMMOTH_TRAP_17 = 188039,
	GO_MAMMOTH_TRAP_18 = 188040,
	GO_MAMMOTH_TRAP_19 = 188041,
	GO_MAMMOTH_TRAP_20 = 188042,
	GO_MAMMOTH_TRAP_21 = 188043,
	GO_MAMMOTH_TRAP_22 = 188044,
};

#define MammothTrapsNum 22
const uint32 MammothTraps[MammothTrapsNum] = { GO_MAMMOTH_TRAP_1,
		GO_MAMMOTH_TRAP_2, GO_MAMMOTH_TRAP_3, GO_MAMMOTH_TRAP_4,
		GO_MAMMOTH_TRAP_5, GO_MAMMOTH_TRAP_6, GO_MAMMOTH_TRAP_7,
		GO_MAMMOTH_TRAP_8, GO_MAMMOTH_TRAP_9, GO_MAMMOTH_TRAP_10,
		GO_MAMMOTH_TRAP_11, GO_MAMMOTH_TRAP_12, GO_MAMMOTH_TRAP_13,
		GO_MAMMOTH_TRAP_14, GO_MAMMOTH_TRAP_15, GO_MAMMOTH_TRAP_16,
		GO_MAMMOTH_TRAP_17, GO_MAMMOTH_TRAP_18, GO_MAMMOTH_TRAP_19,
		GO_MAMMOTH_TRAP_20, GO_MAMMOTH_TRAP_21, GO_MAMMOTH_TRAP_22 };

class npc_trapped_mammoth_calf: public CreatureScript {
public:
	npc_trapped_mammoth_calf() :
			CreatureScript("npc_trapped_mammoth_calf") {
	}

	struct npc_trapped_mammoth_calfAI: public ScriptedAI {
		npc_trapped_mammoth_calfAI(Creature* c) :
				ScriptedAI(c) {
		}

		uint32 uiTimer;
		bool bStarted;

		void Reset() {
			uiTimer = 1500;
			bStarted = false;

			GameObject* pTrap;
			for (uint8 i = 0; i < MammothTrapsNum; ++i) {
				pTrap = me->FindNearestGameObject(MammothTraps[i], 11.0f);
				if (pTrap) {
					pTrap->SetGoState(GO_STATE_ACTIVE);
					return;
				}
			}
		}

		void UpdateAI(const uint32 diff) {
			if (bStarted) {
				if (uiTimer <= diff) {
					Position pos;
					me->GetRandomNearPosition(pos, 10.0f);
					me->GetMotionMaster()->MovePoint(0, pos);
					bStarted = false;
				} else
					uiTimer -= diff;
			}
		}

		void DoAction(const int32 param) {
			if (param == 1)
				bStarted = true;
		}

		void MovementInform(uint32 uiType, uint32 /*uiId*/) {
			if (uiType != POINT_MOTION_TYPE)
				return;
			me->DisappearAndDie();
			GameObject* pTrap;
			for (uint8 i = 0; i < MammothTrapsNum; ++i) {
				pTrap = me->FindNearestGameObject(MammothTraps[i], 11.0f);
				if (pTrap) {
					pTrap->SetLootState(GO_JUST_DEACTIVATED);
					return;
				}
			}
		}
	};

	CreatureAI* GetAI(Creature* creature) const {
		return new npc_trapped_mammoth_calfAI(creature);
	}
};

/*######
 ## Quest 11653: Hah... You're Not So Big Now!
 ######*/

enum eNotSoBig {
	QUEST_YOU_RE_NOT_SO_BIG_NOW = 11653,
	SPELL_AURA_NOTSOBIG_1 = 45672,
	SPELL_AURA_NOTSOBIG_2 = 45673,
	SPELL_AURA_NOTSOBIG_3 = 45677,
	SPELL_AURA_NOTSOBIG_4 = 45681
};

class npc_magmoth_crusher: public CreatureScript {
public:
	npc_magmoth_crusher() :
			CreatureScript("npc_magmoth_crusher") {
	}

	struct npc_magmoth_crusherAI: public ScriptedAI {
		npc_magmoth_crusherAI(Creature* c) :
				ScriptedAI(c) {
		}

		void JustDied(Unit* killer) {
			if (killer->GetTypeId() == TYPEID_PLAYER
					&& CAST_PLR(killer)->GetQuestStatus(
							QUEST_YOU_RE_NOT_SO_BIG_NOW)
							== QUEST_STATUS_INCOMPLETE
					&& (me->HasAura(SPELL_AURA_NOTSOBIG_1)
							|| me->HasAura(SPELL_AURA_NOTSOBIG_2)
							|| me->HasAura(SPELL_AURA_NOTSOBIG_3)
							|| me->HasAura(SPELL_AURA_NOTSOBIG_4))) {
				Quest const* qInfo = sObjectMgr->GetQuestTemplate(
						QUEST_YOU_RE_NOT_SO_BIG_NOW);
				if (qInfo)
					CAST_PLR(killer)->RewardPlayerAndGroupAtEvent(
							uint32(qInfo->ReqCreatureOrGOId[0]), killer);
			}
		}
	};

	CreatureAI* GetAI(Creature* creature) const {
		return new npc_magmoth_crusherAI(creature);
	}
};

/*######
 ## Quest 11608: Bury Those Cockroaches!
 ######*/

#define QUEST_BURY_THOSE_COCKROACHES            11608
#define SPELL_SEAFORIUM_DEPTH_CHARGE_EXPLOSION  45502

class npc_seaforium_depth_charge: public CreatureScript {
public:
	npc_seaforium_depth_charge() :
			CreatureScript("npc_seaforium_depth_charge") {
	}

	struct npc_seaforium_depth_chargeAI: public ScriptedAI {
		npc_seaforium_depth_chargeAI(Creature* c) :
				ScriptedAI(c) {
		}

		uint32 uiExplosionTimer;
		void Reset() {
			uiExplosionTimer = urand(5000, 10000);
		}
		void UpdateAI(const uint32 diff) {
			if (uiExplosionTimer < diff) {
				DoCast(SPELL_SEAFORIUM_DEPTH_CHARGE_EXPLOSION);
				for (uint8 i = 0; i < 4; ++i) {
					if (Creature* cCredit = me->FindNearestCreature(25402 + i, 10.0f)) //25402-25405 credit markers
					{
						if (Unit* uOwner = me->GetOwner()) {
							Player* owner = uOwner->ToPlayer();
							if (owner
									&& owner->GetQuestStatus(
											QUEST_BURY_THOSE_COCKROACHES)
											== QUEST_STATUS_INCOMPLETE)
								owner->KilledMonsterCredit(cCredit->GetEntry(),
										cCredit->GetGUID());
						}
					}
				}
				me->Kill(me);
				return;
			} else
				uiExplosionTimer -= diff;
		}
	};

	CreatureAI* GetAI(Creature* creature) const {
		return new npc_seaforium_depth_chargeAI(creature);
	}
};

/*######
 ## Help Those That Cannot Help Themselves, Quest 11876
 ######*/

enum eValiancekeepcannons {
	GO_VALIANCE_KEEP_CANNON_1 = 187560, GO_VALIANCE_KEEP_CANNON_2 = 188692
};

class npc_valiance_keep_cannoneer: public CreatureScript {
public:
	npc_valiance_keep_cannoneer() :
			CreatureScript("npc_valiance_keep_cannoneer") {
	}

	struct npc_valiance_keep_cannoneerAI: public ScriptedAI {
		npc_valiance_keep_cannoneerAI(Creature* c) :
				ScriptedAI(c) {
		}

		uint32 uiTimer;

		void Reset() {
			uiTimer = urand(13000, 18000);
		}

		void UpdateAI(const uint32 diff) {
			if (uiTimer <= diff) {
				me->HandleEmoteCommand(EMOTE_ONESHOT_KNEEL);
				GameObject* pCannon = me->FindNearestGameObject(
						GO_VALIANCE_KEEP_CANNON_1, 10);
				if (!pCannon)
					pCannon = me->FindNearestGameObject(
							GO_VALIANCE_KEEP_CANNON_2, 10);
				if (pCannon)
					pCannon->Use(me);
				uiTimer = urand(13000, 18000);
			} else
				uiTimer -= diff;

			if (!UpdateVictim())
				return;
		}
	};

	CreatureAI* GetAI(Creature* creature) const {
		return new npc_valiance_keep_cannoneerAI(creature);
	}
};

/*******************************************************
 * npc_warmage_coldarra
 *******************************************************/

enum Spells {
	SPELL_TRANSITUS_SHIELD_BEAM = 48310
};

enum NPCs {
	NPC_TRANSITUS_SHIELD_DUMMY = 27306,
	NPC_WARMAGE_HOLLISTER = 27906,
	NPC_WARMAGE_CALANDRA = 27173,
	NPC_WARMAGE_WATKINS = 27904
};

class npc_warmage_coldarra: public CreatureScript {
public:
	npc_warmage_coldarra() :
			CreatureScript("npc_warmage_coldarra") {
	}

	struct npc_warmage_coldarraAI: public Scripted_NoMovementAI {
		npc_warmage_coldarraAI(Creature* creature) :
				Scripted_NoMovementAI(creature) {
		}

		uint32 m_uiTimer; //Timer until recast

		void Reset() {
			m_uiTimer = 0;
		}

		void EnterCombat(Unit* /*who*/) {
		}

		void AttackStart(Unit* /*who*/) {
		}

		void UpdateAI(const uint32 uiDiff) {
			if (m_uiTimer <= uiDiff) {
				std::list<Creature*> orbList;
				GetCreatureListWithEntryInGrid(orbList, me,
						NPC_TRANSITUS_SHIELD_DUMMY, 32.0f);

				switch (me->GetEntry()) {
				case NPC_WARMAGE_HOLLISTER: {
					if (!orbList.empty()) {
						for (std::list<Creature*>::const_iterator itr =
								orbList.begin(); itr != orbList.end(); ++itr) {
							if (Creature* pOrb = *itr)
								if (pOrb->GetPositionY() > 6680)
									DoCast(pOrb, SPELL_TRANSITUS_SHIELD_BEAM);
						}
					}
					m_uiTimer = urand(90000, 120000);
				}
					break;
				case NPC_WARMAGE_CALANDRA: {
					if (!orbList.empty()) {
						for (std::list<Creature*>::const_iterator itr =
								orbList.begin(); itr != orbList.end(); ++itr) {
							if (Creature* pOrb = *itr)
								if ((pOrb->GetPositionY() < 6680)
										&& (pOrb->GetPositionY() > 6630))
									DoCast(pOrb, SPELL_TRANSITUS_SHIELD_BEAM);
						}
					}
					m_uiTimer = urand(90000, 120000);
				}
					break;
				case NPC_WARMAGE_WATKINS: {
					if (!orbList.empty()) {
						for (std::list<Creature*>::const_iterator itr =
								orbList.begin(); itr != orbList.end(); ++itr) {
							if (Creature* pOrb = *itr)
								if (pOrb->GetPositionY() < 6630)
									DoCast(pOrb, SPELL_TRANSITUS_SHIELD_BEAM);
						}
					}
					m_uiTimer = urand(90000, 120000);
				}
					break;
				}
			} else
				m_uiTimer -= uiDiff;

			ScriptedAI::UpdateAI(uiDiff);

			if (!UpdateVictim())
				return;
		}
	};

	CreatureAI* GetAI(Creature* creature) const {
		return new npc_warmage_coldarraAI(creature);
	}
};

/*######
 ## npc_hidden_cultist
 ######*/

enum eHiddenCultist {
	SPELL_SHROUD_OF_THE_DEATH_CULTIST = 46077, //not working
	SPELL_RIGHTEOUS_VISION = 46078, //player aura

	QUEST_THE_HUNT_IS_ON = 11794,

	GOSSIP_TEXT_SALTY_JOHN_THORPE = 12529,
	GOSSIP_TEXT_GUARD_MITCHELSS = 12530,
	GOSSIP_TEXT_TOM_HEGGER = 12528,

	NPC_TOM_HEGGER = 25827,
	NPC_SALTY_JOHN_THORPE = 25248,
	NPC_GUARD_MITCHELLS = 25828,

	SAY_HIDDEN_CULTIST_1 = -1571044,
	SAY_HIDDEN_CULTIST_2 = -1571045,
	SAY_HIDDEN_CULTIST_3 = -1571046,
	SAY_HIDDEN_CULTIST_4 = -1571047
};

const char* GOSSIP_ITEM_TOM_HEGGER =
		"What do you know about the Cult of the Damned?";
const char* GOSSIP_ITEM_GUARD_MITCHELLS =
		"How long have you worked for the Cult of the Damned?";
const char* GOSSIP_ITEM_SALTY_JOHN_THORPE =
		"I have a reason to believe you're involved in the cultist activity";

class npc_hidden_cultist: public CreatureScript {
public:
	npc_hidden_cultist() :
			CreatureScript("npc_hidden_cultist") {
	}

	struct npc_hidden_cultistAI: public ScriptedAI {
		npc_hidden_cultistAI(Creature* creature) :
				ScriptedAI(creature) {
			uiEmoteState = creature->GetUInt32Value(UNIT_NPC_EMOTESTATE);
			uiNpcFlags = creature->GetUInt32Value(UNIT_NPC_FLAGS);
		}

		uint32 uiEmoteState;
		uint32 uiNpcFlags;

		uint32 uiEventTimer;
		uint8 uiEventPhase;

		uint64 uiPlayerGUID;

		void Reset() {
			if (uiEmoteState)
				me->SetUInt32Value(UNIT_NPC_EMOTESTATE, uiEmoteState);

			if (uiNpcFlags)
				me->SetUInt32Value(UNIT_NPC_FLAGS, uiNpcFlags);

			uiEventTimer = 0;
			uiEventPhase = 0;

			uiPlayerGUID = 0;

			DoCast(SPELL_SHROUD_OF_THE_DEATH_CULTIST);

			me->RestoreFaction();
		}

		void DoAction(const int32 /*iParam*/) {
			me->StopMoving();
			me->SetUInt32Value(UNIT_NPC_FLAGS, 0);
			if (Player* player = me->GetPlayer(*me, uiPlayerGUID)) {
				me->SetInFront(player);
				me->SendMovementFlagUpdate();
			}
			uiEventTimer = 3000;
			uiEventPhase = 1;
		}

		void SetGUID(uint64 uiGuid, int32 /*iId*/) {
			uiPlayerGUID = uiGuid;
		}

		void AttackPlayer() {
			me->setFaction(14);
			if (Player* player = me->GetPlayer(*me, uiPlayerGUID))
				me->AI()->AttackStart(player);
		}

		void UpdateAI(const uint32 uiDiff) {
			if (uiEventTimer && uiEventTimer <= uiDiff) {
				switch (uiEventPhase) {
				case 1:
					switch (me->GetEntry()) {
					case NPC_SALTY_JOHN_THORPE:
						me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
						DoScriptText(SAY_HIDDEN_CULTIST_1, me);
						uiEventTimer = 5000;
						uiEventPhase = 2;
						break;
					case NPC_GUARD_MITCHELLS:
						DoScriptText(SAY_HIDDEN_CULTIST_2, me);
						uiEventTimer = 5000;
						uiEventPhase = 2;
						break;
					case NPC_TOM_HEGGER:
						DoScriptText(SAY_HIDDEN_CULTIST_3, me);
						uiEventTimer = 5000;
						uiEventPhase = 2;
						break;
					}
					break;
				case 2:
					switch (me->GetEntry()) {
					case NPC_SALTY_JOHN_THORPE:
						DoScriptText(SAY_HIDDEN_CULTIST_4, me);
						if (Player* player = me->GetPlayer(*me, uiPlayerGUID)) {
							me->SetInFront(player);
							me->SendMovementFlagUpdate();
						}
						uiEventTimer = 3000;
						uiEventPhase = 3;
						break;
					case NPC_GUARD_MITCHELLS:
					case NPC_TOM_HEGGER:
						AttackPlayer();
						uiEventPhase = 0;
						break;
					}
					break;
				case 3:
					if (me->GetEntry() == NPC_SALTY_JOHN_THORPE) {
						AttackPlayer();
						uiEventPhase = 0;
					}
					break;
				}
			} else
				uiEventTimer -= uiDiff;

			if (!UpdateVictim())
				return;

			DoMeleeAttackIfReady();
		}
	};

	CreatureAI* GetAI(Creature* creature) const {
		return new npc_hidden_cultistAI(creature);
	}

	bool OnGossipHello(Player* player, Creature* creature) {
		uint32 uiGossipText = 0;
		const char* charGossipItem;

		switch (creature->GetEntry()) {
		case NPC_TOM_HEGGER:
			uiGossipText = GOSSIP_TEXT_TOM_HEGGER;
			charGossipItem = GOSSIP_ITEM_TOM_HEGGER;
			break;
		case NPC_SALTY_JOHN_THORPE:
			uiGossipText = GOSSIP_TEXT_SALTY_JOHN_THORPE;
			charGossipItem = GOSSIP_ITEM_SALTY_JOHN_THORPE;
			break;
		case NPC_GUARD_MITCHELLS:
			uiGossipText = GOSSIP_TEXT_GUARD_MITCHELSS;
			charGossipItem = GOSSIP_ITEM_GUARD_MITCHELLS;
			break;
		default:
			charGossipItem = "";
			return false;
		}

		if (player->HasAura(SPELL_RIGHTEOUS_VISION)
				&& player->GetQuestStatus(QUEST_THE_HUNT_IS_ON)
						== QUEST_STATUS_INCOMPLETE)
			player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, charGossipItem, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);

		if (creature->isVendor())
			player->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);

		player->SEND_GOSSIP_MENU(uiGossipText, creature->GetGUID());

		return true;
	}

	bool OnGossipSelect(Player* player, Creature* creature, uint32 /*uiSender*/,
			uint32 uiAction) {
		player->PlayerTalkClass->ClearMenus();

		if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) {
			player->CLOSE_GOSSIP_MENU();
			creature->AI()->SetGUID(player->GetGUID());
			creature->AI()->DoAction(1);
		}

		if (uiAction == GOSSIP_ACTION_TRADE)
			player->GetSession()->SendListInventory(creature->GetGUID());

		return true;
	}
};

/*######
 ## npc_recon_pilot
 ######*/

#define GOSSIP_ITEM_PILOT_1  "Search the body for the pilot's insignia."
#define GOSSIP_ITEM_PILOT_2  "Search the body for the pilot's emergency toolkit."

enum eReconPilot {
	QUEST_EMERGENCY_PROTOCOL_C = 11795,
	QUEST_EMERGENCY_SUPPLIES = 11887,
	SPELL_SUMMON_INSIGNIA = 46166,
	SPELL_GIVE_EMERGENCY_KIT = 46362,
	GOSSIP_TEXT_PILOT = 12489
};

class npc_recon_pilot: public CreatureScript {
public:
	npc_recon_pilot() :
			CreatureScript("npc_recon_pilot") {
	}

	bool OnGossipHello(Player* pPlayer, Creature* creature) {
		if (pPlayer->GetQuestStatus(QUEST_EMERGENCY_PROTOCOL_C)
				== QUEST_STATUS_INCOMPLETE)
			pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_PILOT_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);

		if (pPlayer->GetQuestStatus(QUEST_EMERGENCY_SUPPLIES)
				== QUEST_STATUS_INCOMPLETE)
			pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_PILOT_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);

		pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_PILOT,
				creature->GetGUID());
		return true;
	}

	bool OnGossipSelect(Player* pPlayer, Creature* creature,
			uint32 /*uiSender*/, uint32 uiAction) {
		pPlayer->PlayerTalkClass->ClearMenus();

		switch (uiAction) {
		case GOSSIP_ACTION_INFO_DEF + 1:
			creature->CastSpell(pPlayer, SPELL_SUMMON_INSIGNIA, true);
			break;
		case GOSSIP_ACTION_INFO_DEF + 2:
			creature->CastSpell(pPlayer, SPELL_GIVE_EMERGENCY_KIT, true);
			break;
		}

		pPlayer->CLOSE_GOSSIP_MENU();
		creature->DespawnOrUnsummon();

		return true;
	}
};

/*####
 # mob_steam_rager
 ####*/

enum eSteamRager {
	SPELL_STEAM_BLAST = 50375,
	SPELL_ENERGY_TRANSFER = 46399,
	QUEST_POWER_OF_ELEMENTS = 11893,
	ENTRY_WINDSOUL_TOTEM = 25987
};

class mob_steam_rager: public CreatureScript {
public:
	mob_steam_rager() :
			CreatureScript("mob_steam_rager") {
	}

	CreatureAI* GetAI(Creature* creature) const {
		return new mob_steam_ragerAI(creature);
	}

	struct mob_steam_ragerAI: public ScriptedAI {
		mob_steam_ragerAI(Creature *c) :
				ScriptedAI(c) {
		}

		uint32 uiSteamBlastTimer;

		void Reset() {
			uiSteamBlastTimer = urand(3000, 5000);
		}

		void UpdateAI(const uint32 diff) {
			if (!UpdateVictim())
				return;

			if (uiSteamBlastTimer <= diff) {
				DoCast(me->getVictim(), SPELL_STEAM_BLAST, false);
				uiSteamBlastTimer = urand(7000, 10000);
			} else
				uiSteamBlastTimer -= diff;

			DoMeleeAttackIfReady();
		}

		void JustDied(Unit* Killer) {
			if (Killer->GetTypeId() == TYPEID_PLAYER) {
				if (Killer->ToPlayer()->GetQuestStatus(QUEST_POWER_OF_ELEMENTS)
						== QUEST_STATUS_INCOMPLETE) {
					if (Unit* pTotem = me->FindNearestCreature(ENTRY_WINDSOUL_TOTEM, 25.0f)) {
						DoCast(pTotem, SPELL_ENERGY_TRANSFER, true);
						Killer->ToPlayer()->RewardPlayerAndGroupAtEvent(
								ENTRY_WINDSOUL_TOTEM, Killer);
					}
				}
			}
		}
	};
};

/*###################
 # npc_q11796_trigger
 ####################*/

class npc_q11796_trigger: public CreatureScript {
public:
	npc_q11796_trigger() :
			CreatureScript("npc_q11796_trigger") {
	}

	enum q11796TriggerData {
		GO_TEMP_CRASHED_FLYING_MACHINE = 300181,
		EASTERN_WRECK_GUID = 99826,
		SOUTHERN_WRECK_GUID = 99827,
		NORTHWESTERN_WRECK_GUID = 99828,
		EASTERN_WRECK_KC = 25847,
		SOUTHERN_WRECK_KC = 25846,
		NORTHWESTERN_WRECK_KC = 25845,
		SPELL_EMERGENCY_TORCH = 46171
	};

	struct npc_q11796_triggerAI: public ScriptedAI {
		npc_q11796_triggerAI(Creature* creature) :
				ScriptedAI(creature) {
		}

		void Reset() {
		}

		void SpellHit(Unit* caster, const SpellEntry* spell) {
			if (caster->GetTypeId() != TYPEID_PLAYER)
				return;

			if (caster->GetTypeId() == TYPEID_PLAYER
					&& spell->Id == SPELL_EMERGENCY_TORCH) {
				if (GameObject* go = me->FindNearestGameObject(GO_TEMP_CRASHED_FLYING_MACHINE,10.0f)) {
					switch (go->GetGUIDLow()) {
					case EASTERN_WRECK_GUID:
						caster->ToPlayer()->KilledMonsterCredit(
								EASTERN_WRECK_KC, 0);
						break;
					case SOUTHERN_WRECK_GUID:
						caster->ToPlayer()->KilledMonsterCredit(
								SOUTHERN_WRECK_KC, 0);
						break;
					case NORTHWESTERN_WRECK_GUID:
						caster->ToPlayer()->KilledMonsterCredit(
								NORTHWESTERN_WRECK_KC, 0);
						break;
					}
				}
			}
		}
	};

	CreatureAI* GetAI(Creature* creature) const {
		return new npc_q11796_triggerAI(creature);
	}
};

/*##########################
 ## npc_fallen_caravan_guard - quest fix 11593 and 11658
 ###########################*/

#define GOSSIP_ITEM_GUARD_1 "Search the body for the guard's outfit"
#define GOSSIP_ITEM_GUARD_2 "Burn corpse to purify its soul"

class npc_fallen_caravan_guard: public CreatureScript {
public:
	npc_fallen_caravan_guard() :
			CreatureScript("npc_fallen_caravan_guard") {
	}

	enum FallenCaravanData {
		QUEST_PLAN_B = 11658,
		QUEST_THE_HONORED_DEAD = 11593,
		ITEM_WARSONG_OUTFIT = 34842,
		SPELL_RAGEFIST_TORCH = 45474,
		GOSSIP_TEXT_GUARD = 12388,
		NPC_BURNED_CORPSE_KC = 25342
	};

	bool OnGossipHello(Player* player, Creature* creature) {
		if (player->GetQuestStatus(QUEST_PLAN_B) == QUEST_STATUS_INCOMPLETE)
			player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_GUARD_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);

		if (player->GetQuestStatus(QUEST_THE_HONORED_DEAD)
				== QUEST_STATUS_INCOMPLETE)
			player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_GUARD_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);

		player->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_GUARD,
				creature->GetGUID());
		return true;
	}

	bool OnGossipSelect(Player* player, Creature* creature, uint32 /*uiSender*/,
			uint32 uiAction) {
		player->PlayerTalkClass->ClearMenus();

		switch (uiAction) {
		case GOSSIP_ACTION_INFO_DEF + 1:
			player->AddItem(ITEM_WARSONG_OUTFIT, 1);
			break;
		case GOSSIP_ACTION_INFO_DEF + 2:
			player->CastSpell(creature, SPELL_RAGEFIST_TORCH, false);
			player->KilledMonsterCredit(NPC_BURNED_CORPSE_KC, 0);
			break;
		}

		player->CLOSE_GOSSIP_MENU();
		creature->DespawnOrUnsummon();

		return true;
	}
};

/*#####################
 # item_snq_control_unit (34981)
 #######################*/

class item_snq_control_unit: public ItemScript {
public:

	item_snq_control_unit() :
			ItemScript("item_snq_control_unit") {
	}

	bool OnUse(Player* player, Item* /*item*/,
			SpellCastTargets const& /*targets*/) {
		if (player->GetQuestStatus(11723) == QUEST_STATUS_INCOMPLETE)
			player->SummonCreature(25629, 3511.959961f, 4527.180176f,
					-12.994900f, 0.357893f,
					TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
		return true;
	}
};

/*###################################
 # item_interdimensional_refabricator (35479)
 ####################################*/

class item_interdimensional_refabricator: public ItemScript {
public:

	item_interdimensional_refabricator() :
			ItemScript("item_interdimensional_refabricator") {
	}

	bool OnUse(Player* player, Item* /*item*/,
			SpellCastTargets const& /*targets*/) {
		if (player->GetQuestStatus(11905) == QUEST_STATUS_INCOMPLETE)
			player->CastSpell(player, 46547, false);
		player->KilledMonsterCredit(26105, 0);
		return true;
	}
};

void AddSC_borean_tundra() {
	new npc_sinkhole_kill_credit();
	new npc_khunok_the_behemoth();
	new npc_keristrasza();
	new npc_corastrasza();
	new vehicle_wyrmrest_skytalon();
	new npc_iruk();
	new mob_nerubar_victim();
	new npc_scourge_prisoner();
	new npc_jenny();
	new npc_fezzix_geartwist();
	new npc_nesingwary_trapper();
	new npc_lurgglbr();
	new npc_nexus_drake_hatchling();
	new npc_thassarian();
	new npc_image_lich_king();
	new npc_counselor_talbot();
	new npc_leryssa();
	new npc_general_arlos();
	new npc_beryl_sorcerer();
	new npc_imprisoned_beryl_sorcerer();
	new npc_mootoo_the_younger();
	new npc_bonker_togglevolt();
	new npc_trapped_mammoth_calf();
	new npc_magmoth_crusher();
	new npc_seaforium_depth_charge();
	new npc_valiance_keep_cannoneer();
	new npc_warmage_coldarra();
	new npc_hidden_cultist();
	new npc_recon_pilot();
	new npc_q11796_trigger();
	new npc_fallen_caravan_guard();
	new item_snq_control_unit();
	new item_interdimensional_refabricator();
}
